メインコンテンツまでスキップ

Git サブモジュールの作成

目標: A プロジェクト内に B プロジェクトを作成し、B プロジェクトを独立したリポジトリとして、git submodule の方法で A プロジェクトに導入する。


一、なぜサブモジュール(submodule)を使用するのか

git submodule を使用する核心的な理由は:

  • B プロジェクトは独立して開発・リリースできる
  • A プロジェクトは B の特定のバージョンのみを参照する
  • 複数のプロジェクトが同じ B を再利用できる
  • すべてのコードを 1 つのリポジトリに詰め込むことを避ける(疑似 monorepo)

適切なシーン:

  • SDK / ユーティリティライブラリ
  • 基本コンポーネント
  • 独立した CI / リリースが必要なモジュール

二、全体的なプロセス概要

  1. A プロジェクト内に B プロジェクトディレクトリを作成
  2. B プロジェクトを独立した Git リポジトリとして初期化
  3. gh を使用してリモートリポジトリを作成しプッシュ
  4. B プロジェクトを submodule として A プロジェクトに追加
  5. A プロジェクトの submodule 変更をコミット

三、A プロジェクト内に B プロジェクトを作成

A プロジェクトのルートディレクトリに移動:

cd A-project

B プロジェクトディレクトリを作成(例):

mkdir -p packages/B-project
cd packages/B-project

四、B プロジェクトリポジトリの初期化

1. Git を初期化

git init

2. 初期コミットを作成(必須)

echo "# B-project" > README.md
git add .
git commit -m "chore: initial commit"

⚠️ submodule はコミットのないリポジトリを参照できません


五、GitHub CLI を使用してリモートリポジトリを作成

GitHub にログインしていることを確認:

gh auth status

リポジトリを作成してプッシュ(fish / bash 共通の書き方):

gh repo create B-project --private --source=. --remote=origin --push

パブリックリポジトリの場合は、--private--public に変更してください

リモートリポジトリを確認:

git remote -v

六、B プロジェクトをサブモジュールとして A プロジェクトに追加

1. A プロジェクトのルートディレクトリに戻る

cd ../../

2. ローカルの B ディレクトリを削除(重要なステップ)

rm -rf packages/B-project

⚠️ submodule は自動的にリポジトリをクローンするため、ローカルディレクトリは空である必要があります


3. submodule を追加

git submodule add https://github.com/<ユーザー名または組織>/B-project.git packages/B-project

成功後、以下が生成されます:

  • packages/B-project/
  • .gitmodules

七、A プロジェクトの submodule 変更をコミット

git add .gitmodules packages/B-project
git commit -m "chore: add B-project as submodule"
git push

八、日常の開発と更新プロセス

1. B プロジェクトを開発

cd packages/B-project
git checkout main

変更してコミット:

git add .
git commit -m "feat: xxx"
git push

2. A プロジェクト内でサブモジュールバージョンを更新

cd ../../
git status

以下のように表示されます:

modified: packages/B-project (new commits)

更新をコミット:

git add packages/B-project
git commit -m "chore: bump B-project submodule"
git push

九、submodule を含むプロジェクトをクローン

推奨方法(一度に)

git clone --recurse-submodules <A-project-repo>

既にクローンしたプロジェクトにサブモジュールを追加

git submodule update --init --recursive

十、よくある落とし穴のまとめ

❌ B プロジェクトの初期コミットを忘れた

→ submodule を追加できません

❌ ローカルディレクトリを削除せずに submodule を追加

already exists and is not a git repository

❌ B を更新したが、A の submodule ポインタをコミットしなかった

→ 他の人は最新バージョンを取得できません


十一、補足の提案

  • サブモジュールを packages/ または libs/ ディレクトリに統一
  • submodule の更新は個別のコミットが必須
  • チーム内で約束:submodule の detached HEAD を直接変更することを禁止

結論: submodule が管理するのは「依存関係のコミット」であり、コード自体ではありません。 「誰がリリースを担当し、誰が参照するのか」を明確にすれば、落とし穴を避けられます。


ご希望であれば、このノートを以下の形式に変更することもできます:

  • チーム規範版
  • README 簡潔版
  • フローチャート付きバージョン